;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, or dbx under Emacs
;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Version: 1.2
+;; Version: 1.3
;; Keywords: unix, tools
;; Copyright (C) 1992 Free Software Foundation, Inc.
;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
;; who also hacked the mode to use comint.el.
-;; This code will not work under Emacs 18. It relies on Emacs 19's
-;; minor-mode-keymap support and the find-tag-noselect entry point of etags.
-
;;; Code:
(require 'comint)
(require 'etags)
;; ======================================================================
-;; minor-mode machinery for C buffers visited by GUD
+;; GUD commands must be visible in C buffers visited by GUD
(defvar gud-key-prefix "\C-x\C-a"
- "Prefix of all GUD minor-mode commands valid in C buffers.")
-
-(defvar gud-minor-mode nil)
-(or (assq 'gud-minor-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(gud-minor-mode " GUD") minor-mode-alist)))
-
-(defvar gud-mode-map nil)
-(if gud-mode-map
- nil
- (setq gud-mode-map (make-sparse-keymap))
- (define-key gud-mode-map gud-key-prefix (make-sparse-keymap))
- (define-key gud-mode-map (concat gud-key-prefix "\C-l") 'gud-refresh)
- )
+ "Prefix of all GUD commands valid in C buffers.")
-(or (assq 'gud-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons
- (cons 'gud-minor-mode gud-mode-map)
- minor-mode-map-alist)))
-
-(defun gud-minor-mode (&optional enable)
- "GUD minor mode is enabled in C buffers visited due to a GUD stop at
-breakpoint. All GUD-specific commands defined in GUD major mode will work,
-but they get their current file and current line number from the context of
-this buffer."
- (interactive "P")
- (setq gud-minor-mode
- (if (null enable) (not gud-minor-mode)
- (> (prefix-numeric-value enable) 0)))
-)
+(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
+(global-set-key "\C-x " 'gud-break) ;; backward compatibility hack
;; ======================================================================
;; the overloading mechanism
;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
;; which defines FUNC to send the command NAME to the debugger, gives
;; it the docstring DOC, and binds that function to KEY in the GUD
-;; major mode. The function is also bound in the GUD minor-mode
-;; keymap. If a numeric prefix argument is given to FUNC, it gets
-;; sent after NAME.
+;; major mode. The function is also bound in the global keymap with the
+;; GUD prefix.
(defmacro gud-def (func cmd key &optional doc)
"Define FUNC to be a command sending STR and bound to KEY, with
%a text of the hexadecimal address surrounding point
%p prefix argument to the command (if any) as a number
- The `current' source file is the file of the current buffer (if we're in a
-C file with gud-minor-mode active) or the source file current at the last
-break or step (if we're in the GUD buffer).
- The `current' line is that of the current buffer (if we're in a source
-file with gud-minor-mode active) or the source line number at the last
-break or step (if we're in the GUD buffer)."
+ The `current' source file is the file of the current buffer (if
+we're in a C file) or the source file current at the last break or
+step (if we're in the GUD buffer).
+ The `current' line is that of the current buffer (if we're in a
+source file) or the source line number at the last break or step (if
+we're in the GUD buffer)."
(list 'progn
(list 'defun func '(arg)
(or doc "")
'(interactive "p")
(list 'gud-call cmd 'arg))
(if key
- (list 'define-key
- 'gud-mode-map
- (concat gud-key-prefix key)
- (list 'quote func)))))
+ (progn
+ (list 'define-key
+ '(current-local-map)
+ (concat "\C-c" key)
+ (list 'quote func))
+ (list 'global-set-key
+ (concat gud-key-prefix key)
+ (list 'quote func))
+ ))))
;; Where gud-display-frame should put the debugging arrow. This is
;; set by the marker-filter, which scans the debugger's output for
(gud-find-file . gud-gdb-find-file)
))
+ (gud-common-init args)
+
(gud-def gud-break "break %f:%l" "b" "Set breakpoint at current line.")
(gud-def gud-tbreak "tbreak %f:%l" "t" "Set breakpoint at current line.")
(gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line")
(gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
(gud-def gud-print "print %e" "p" "Evaluate C expression at point.")
- (gud-common-init args)
-
(setq comint-prompt-regexp "^(.*gdb[+]?) *")
(run-hooks 'gdb-mode-hook)
)
"Run sdb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
-
(interactive "sRun sdb (like this): sdb ")
-
(if (and gud-sdb-needs-tags
(not (and (boundp 'tags-file-name) (file-exists-p tags-file-name))))
(error "The sdb support requires a valid tags table to work."))
(gud-find-file . gud-sdb-find-file)
))
+ (gud-common-init args)
+
(gud-def gud-break "%l b" "b" "Set breakpoint at current line.")
(gud-def gud-tbreak "%l c" "t" "Set temporary breakpoint at current line.")
(gud-def gud-remove "%l d" "d" "Remove breakpoint at current line")
(gud-def gud-cont "c" "r" "Continue with display.")
(gud-def gud-print "%e/" "p" "Evaluate C expression at point.")
- (gud-common-init args)
-
(setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
(run-hooks 'sdb-mode-hook)
)
(gud-find-file . gud-dbx-find-file)
))
+ (gud-common-init args)
+
(gud-def gud-break "stop at \"%f\":%l"
"b" "Set breakpoint at current line.")
(gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line")
(gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
(gud-def gud-print "print %e" "p" "Evaluate C expression at point.")
- (gud-common-init args)
(setq comint-prompt-regexp "^[^)]*dbx) *")
-
(run-hooks 'dbx-mode-hook)
)
interaction buffer and any source buffer GUD visits due to a breakpoint stop
or step operation:
-\\{gud-mode-map}
-
\\[gud-break] sets a breakpoint at the current file and line. In the
GUD buffer, the current file and line are those of the last breakpoint or
step. In a source buffer, they are the buffer's file and current line.
(setq mode-name "Debugger")
(setq mode-line-process '(": %s"))
(use-local-map (copy-keymap comint-mode-map))
- (define-key (current-local-map)
- gud-key-prefix (lookup-key gud-mode-map gud-key-prefix))
- (define-key (current-local-map)
- "\C-c" (lookup-key gud-mode-map gud-key-prefix))
(make-local-variable 'gud-last-frame)
(setq gud-last-frame nil)
(make-local-variable 'comint-prompt-regexp)
;; buffer killed
;; Stop displaying an arrow in a source file.
(setq overlay-arrow-position nil)
- (setq gud-minor-mode nil)
(set-process-buffer proc nil))
((memq (process-status proc) '(signal exit))
;; Stop displaying an arrow in a source file.
- (setq gud-minor-mode nil)
(setq overlay-arrow-position nil)
;; Fix the mode line.
(setq mode-line-process
(let* ((buffer (gud-find-file true-file))
(window (display-buffer buffer))
(pos))
+ (if (equal buffer (current-buffer))
+ nil
+ (setq buffer-read-only nil))
(save-excursion
(set-buffer buffer)
- (make-local-variable 'gud-minor-mode)
- (setq gud-minor-mode t)
+ (setq buffer-read-only t)
(save-restriction
(widen)
(goto-line line)
;;; The gud-call function must do the right thing whether its invoking
;;; keystroke is from the GUD buffer itself (via major-mode binding)
-;;; or a C buffer in GUD minor mode. In the former case, we want to
-;;; supply data from gud-last-frame. Here's how we do it:
+;;; or a C buffer. In the former case, we want to supply data from
+;;; gud-last-frame. Here's how we do it:
(defun gud-format-command (str arg)
- (let ((minor (not (eq (current-buffer) gud-comint-buffer))))
+ (let ((insource (not (eq (current-buffer) gud-comint-buffer))))
(if (string-match "\\(.*\\)%f\\(.*\\)" str)
(progn
(setq str (concat
(substring str (match-beginning 1) (match-end 1))
- (if minor
+ (if insource
(buffer-file-name)
(car gud-last-frame))
(substring str (match-beginning 2) (match-end 2))))))
(progn
(setq str (concat
(substring str (match-beginning 1) (match-end 1))
- (if minor
+ (if insource
(save-excursion
(beginning-of-line)
(save-restriction (widen)
)
)
+;;; There appears to be a bug in the byte compiler somewhere near macro
+;;; handling that (a) generates a spurious message about gud-key-prefix
+;;; when the global-set-key clause in gud-def is compiled, (b) generates
+;;; incorrect bytecode for gud-def. The symptom of this incorrectness
+;;; is that loading gud.elc brings in a compiled gud-def that doesn't
+;;; properly perform both global (C-x C-a) and local (C-c) bindings.
+;;; The workaround is to always load from source. Consequently, we try
+;;; to disable byte-compilation here.
+;;;
+;;; Local Variables:
+;;; no-byte-compile: t
+;;; End:
+
;;; gud.el ends here